/*
 Copyright 2009 Abdulla Abdurakhmanov (abdulla@latestbit.com)
 Original sources are available at www.latestbit.com

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.

 TCPConnection.hpp. Created on: 20.08.2009 15:30:36
 */

#ifndef TCPCONNECTION_HPP_
#define TCPCONNECTION_HPP_

#include "TCPSharedResources.hpp"
#include "smartobjects/SmartObjectsDefs.hpp"
#include "smartobjects/network/IConnection.hpp"
#include "smartobjects/network/IPacketFormer.hpp"
#include "smartobjects/network/IHandshakeManager.hpp"
#include "smartobjects/exceptions/InvalidPacketReceivedException.hpp"
#include "smartobjects/exceptions/HandshakeException.hpp"
#include "SocketMultiplexer.hpp"
#include "SocketURI.hpp"


namespace smartobjects {

class TCPConnection : public virtual IConnection {
public:
	SO_DLLPRFX TCPConnection( TCPSharedResources::SharedPtr poSharedResources );

	SO_DLLPRFX virtual ~TCPConnection();

	SO_DLLPRFX virtual void close(void) ;
	SO_DLLPRFX virtual bool isOpen(void) ;
	SO_DLLPRFX virtual URI* getEndpointURI(void) ;

	SO_DLLPRFX virtual void send(const ByteBuffer*) throw (const IOException&);

	SO_DLLPRFX virtual void addConnectionListener(IConnectionListener*) ;
	SO_DLLPRFX virtual void delConnectionListener(IConnectionListener*) ;
	SO_DLLPRFX virtual void addStreamListener(IStreamListener*) ;
	SO_DLLPRFX virtual void delStreamListener(IStreamListener*) ;

	SO_DLLPRFX virtual IHandshakeManager* getHandshakeManager();
	SO_DLLPRFX virtual IPacketFormer* getPacketFormer();

	SO_DLLPRFX virtual IDataEncrypter* getDataEncrypter();
	SO_DLLPRFX virtual void setDataEncrypter(IDataEncrypter*);

	SO_DLLPRFX virtual IUserCredentials* getUserCredentials();
	SO_DLLPRFX virtual void setUserCredentials(IUserCredentials*);

	SO_DLLPRFX virtual void setEndpointURI(smartobjects::sockets::SocketURI*);

	SO_DLLPRFX void setSocket(smartobjects::sockets::Socket hSocket);
	SO_DLLPRFX smartobjects::sockets::Socket getSocket();

	SO_DLLPRFX void start() throw (const IOException&);

protected:
	SO_DLLPRFX virtual void onAsyncReceive(bool bIsOOB) throw();
	SO_DLLPRFX virtual void onAsyncWrite() throw();
	SO_DLLPRFX virtual void onCheckKeepAlive() throw();

	SO_DLLPRFX virtual void fireOnConnected() = 0;
	SO_DLLPRFX virtual void fireOnDisconnected();
	SO_DLLPRFX virtual void fireOnReceiveError(const std::string& sErrorMessage);
	SO_DLLPRFX virtual void fireOnWriteError(const std::string& sErrorMessage);
	SO_DLLPRFX virtual void fireOnReceived( ByteBuffer* poBuffer );

	SO_DLLPRFX void processingPostActionConnectionListeners();
	SO_DLLPRFX void processingPostActionStreamListeners();
	SO_DLLPRFX bool isHandshaked();

protected:
	static const int READ_BUFFER_SIZE;
	static const int WRITE_BUFFER_SIZE;
	static const int KEEP_ALIVE_MAX_INACTIVITY_TIMEOUT;
	static const char* CONNECTION_MULTIPLEXER_GROUP_NAME;
	static const char* CONNECTION_SENDER_THREAD_POOL_GROUP_NAME;

	TCPSharedResources::SharedPtr m_poSharedResources;
	smartobjects::sockets::SocketMultiplexer::SharedPtr m_poMultiplexer;

	smartobjects::sockets::Socket m_hSocket;
	ThreadPool::SharedPtr m_poThreadPool;
	ThreadPool::TaskId m_nSenderTaskId;

	ByteBuffer* m_poReadBuffer;
	ByteBuffer* m_poWriteBuffer;
	smartobjects::sockets::SocketURI* m_poSocketURI;

	bool m_bStoppedState;
	bool m_bIsMultiplexed;
	boost::recursive_mutex m_mxSocketLock;
	boost::recursive_mutex m_mxAsyncEvent;
	boost::recursive_mutex m_mxWriteBufferLock;

	IPacketFormer* m_poPacketFormer;
	IHandshakeManager* m_poHandshakeManager;

	typedef std::list<IConnectionListener*> ConnectionListeners;
	ConnectionListeners m_aConnectionListeners;
	PostActionListenersContainer<IConnectionListener> m_oPALConnectionListeners;
	boost::recursive_mutex m_mxConnectionListeners;

	typedef std::list<IStreamListener*> StreamListeners;
	StreamListeners m_aStreamListeners;
	PostActionListenersContainer<IStreamListener> m_oPALStreamListeners;

	boost::recursive_mutex m_mxStreamListeners;

	IDataEncrypter* m_poDataEncrypter;
	IUserCredentials* m_poUserCredentials;
	time_t m_nLastActivityTime;
};

}

#endif /* TCPCONNECTION_HPP_ */
